﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WorkFlowCore.Authorization;
using WorkFlowCore.Host.ViewModels;
using WorkFlowCore.Host.ViewModels.WorkFlowCore;
using WorkFlowCore.UserSelectors;
using WorkFlowCore.Workflows;
using WorkFlowCore.WorkTasks;
using Mapster;
using WorkFlowCore.IRepositories;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Application.Dtos;
using Microsoft.AspNetCore.Authorization;
using WorkFlowCore.Conditions;
using WorkFlowCore.Framework.UserSelectors;
using System.Linq.Expressions;
using WorkFlowCore.FormDesigns;
using WorkFlowCore.Common.Tracers;
using WorkFlowCore.Host.ViewModels.FormDesigns;

namespace WorkFlowCore.Host.Controllers
{
    /// <summary>
    /// 流程设计相关
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class WorkflowDesignController : AbpControllerBase
    {
        private ConditionManager conditionManager;
        private UserSelectorManager userSelectorManager;
        private WorkflowManager workflowManager;
        private WorkTaskManager workTaskManager;
        private IWorkflowRepository workflowRepository;
        private IBasicRepository<WorkflowVersionInfo, Guid> versionRepository;
        private FormDesignManager formDesignManager;


        public WorkflowDesignController(ConditionManager conditionManager,
            WorkflowManager workflowManager,
            IWorkflowRepository workflowRepository,
            IWorkTaskRepository worktaskRepository,
            IBasicRepository<WorkflowVersionInfo, Guid> versionRepository,
            IWorkflowSession workflowSession, WorkTaskManager workTaskManager,
            UserSelectorManager userSelectorManager,
            FormDesignManager formDesignManager)
        {
            this.conditionManager = conditionManager;
            this.workflowManager = workflowManager;
            this.workflowRepository = workflowRepository;
            this.versionRepository = versionRepository;
            this.workTaskManager = workTaskManager;
            this.userSelectorManager = userSelectorManager;
            this.formDesignManager = formDesignManager;
        }
        /// <summary>
        /// 获取所有条件项
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllconditions")]
        public async Task<IEnumerable<ConditionDto>> GetAllconditions()
        {
            return conditionManager.AllConditions.Select(c => new ConditionDto { Id = c.Id, Name = c.Name, Description = c.Description, Enabled = c.Enabled });
        }
        /// <summary>
        /// 获取所有的用户选择器
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllUserSelectors")]
        public async Task<IEnumerable<UserSeletorDto>> GetAllUserSelectors()
        {
            return userSelectorManager.UserSelectors.Select(us => new UserSeletorDto { Id = us.Id, Name = us.Name, Description = us.Description, Enabled = us.Enabled });
        }
        /// <summary>
        /// 根据用户选择器获取用户选项（大类）
        /// </summary>
        /// <param name="userSelectorId">用户选择器标识</param>
        /// <returns></returns>
        [HttpGet("GetUserSelectionsOfUserSelector")]
        public async Task<List<Selection>> GetUserSelectionsOfUserSelector(string userSelectorId)
        {
            using (var activity = WorkflowActivitySource.Source?.StartActivity("GetUserSelectionsOfUserSelector"))
            {
                return await workTaskManager.GetUserSelectionsOfUserSelector(userSelectorId);
            }

        }

        /// <summary>
        /// 根据用户选项（大类）获取用户列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetUsersOfUserSelecton")]
        public async Task<List<Selection>> GetUsersOfUserSelecton([FromQuery] GetUsersOfUserSelectonInput input)
        {
            return await userSelectorManager.GetUsersOfUserSelecton(input.userSelectorId, input.InputSelectionIds);
        }

        /// <summary>
        /// 创建新流程设计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateWorkFlow")]
        public async Task<Workflow> CreateWorkFlow(CreateWorkFlowInput input)
        {
            return await workflowManager.CreateWorkflow(input.Name, input.Des, input.Type);
        }
        /// <summary>
        /// 获取所有流程设计（包含版本）列表
        /// 用于在表单设计时筛选流程设计版本
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowsWithDefaultVersion")]
        public async Task<List<GetAllWorkflowsWithVersionOutput>> GetAllWorkflowsWithDefaultVersion()
        {
            return (await workflowRepository.GetListAsync())
                .OrderByDescending(w => w.IsLock)
                .ThenByDescending(w => w.WorkflowType)
                .ThenByDescending(w => w.ModifiedTime)
                .ThenByDescending(w => w.Name).Select(w => new GetAllWorkflowsWithVersionOutput
                {
                    ActiveVersion = w.ActiveVersion,
                    Id = w.Id,
                    Name = w.Name,
                    WorkflowNo = w.WorkflowNo,
                    WorkflowType = w.WorkflowType,
                    Description = w.Description,
                }).ToList();
        }

        /// <summary>
        /// 获取所有流程设计（包含版本）列表 --按类型分组
        /// 用于在表单设计时筛选流程设计版本
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowsWithDefaultVersionGroup")]
        public async Task<List<GetAllWorkflowsWithVersionGroupOutput>> GetAllWorkflowsWithDefaultVersionGroup()
        {
            return (await workflowRepository.GetListAsync())
                .OrderByDescending(w => w.IsLock)
                .ThenByDescending(w => w.WorkflowType)
                .ThenByDescending(w => w.ModifiedTime)
                .ThenByDescending(w => w.Name).Select(w => new GetAllWorkflowsWithVersionOutput
                {
                    ActiveVersion = w.ActiveVersion,
                    Id = w.Id,
                    Name = w.Name.IsNullOrWhiteSpace()?"（未命名）":w.Name,
                    WorkflowNo = w.WorkflowNo,
                    WorkflowType = w.WorkflowType,
                    Description = w.Description,
                })
                .GroupBy(w => string.IsNullOrWhiteSpace(w.WorkflowType) ? "（未分类）" : w.WorkflowType)
                .Select(g => new GetAllWorkflowsWithVersionGroupOutput
                {
                    WorkflowType = g.Key,
                    items = g.ToArray(),
                })
                .ToList();
        }

        /// <summary>
        /// 获取流程所有版本信息
        /// </summary>
        /// <param name="workflowId"></param>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowVersions")]
        public async Task<IEnumerable<GetAllWorkflowVersionOutput>> GetAllWorkflowVersions(Guid workflowId)
        {
            return (await versionRepository.GetListAsync(v => v.WorkflowId == workflowId)).Select(v => new GetAllWorkflowVersionOutput
            {
                WorkflowId = v.WorkflowId,
                VersionNo = v.VersionNo,
                Description = v.Description,
                CreationTime = v.CreationTime,
                ModifiedTime = v.ModifiedTime,
                IsLock = v.IsLock,
            }).OrderBy(w => w.VersionNo);
        }
        /// <summary>
        /// 获取流程具体版本信息
        /// </summary>
        /// <param name="versionNo">版本编号</param>
        /// <param name="id">设计id</param>
        /// <returns></returns>
        [HttpGet("GetWorkflowVersion")]
        public async Task<GetWorkflowVersionOutput> GetWorkflowVersion(int versionNo, Guid id)
        {
            var version = await workflowManager.GetWorkflowVersion(id, versionNo);
            return version.Adapt<GetWorkflowVersionOutput>();
        }

        /// <summary>
        /// 根据任务id获取流程具体版本信息
        /// </summary>
        /// <param name="workTaskId">任务id</param>
        /// <returns></returns>
        [HttpGet("GetWorkflowVersionByTaskId")]
        public async Task<GetWorkflowVersionOutput> GetWorkflowVersionByTaskIdAsync(Guid workTaskId)
        {
            var task = await workTaskManager.GetWorkTaskAsync(workTaskId);
            if (task == null) return null;
            var version = await workflowManager.GetWorkflowVersion(task.WorkflowId.Id, task.WorkflowId.VersionNo);
            return version.Adapt<GetWorkflowVersionOutput>();
        }

        /// <summary>
        /// 删除流程
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("Delete")]
        public async Task<bool> Delete(Guid id)
        {
            var result = await workflowManager.DeleteWorkflow(id);
            return result;
        }

        /// <summary>
        /// 删除流程版本
        /// </summary>
        /// <param name="id">设计id</param>
        /// <param name="versionNo">版本编号</param>
        /// <returns></returns>
        [HttpDelete("DeleteWorkflowVersion")]
        public async Task<bool> DeleteWorkflowVersion(Guid id, int versionNo)
        {
            var result = await workflowManager.DeleteWorkflowVersion(id, versionNo);
            return result;
        }
        /// <summary>
        /// 更新流程激活的版本
        /// </summary>
        /// <param name="input"></param>
        [HttpPut("UpdateWorkflowActiveVersion")]
        public async Task<bool> UpdateWorkflowActiveVersion(UpdateWorkflowActiveVersionInput input)
        {
            var result = await workflowManager.UpdateWorkflowActiveVersion(input.WorkflowId, input.ActiveVersion);
            return result;
        }


        /// <summary>
        /// 更新流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPut("UpdateWorkFlow")]
        public async Task<Workflow> UpdateWorkFlow(UpdateWorkFlowInput input)
        {
            return await workflowManager.UpdateWorkflow(input.WorkflowId.Id, input.Name, input.Des, input.Type, input.WorkflowId.VersionNo, input.DrawingInfo, input.VersionDescription
                , input.WorkflowLines.Select(line => new WorkflowLine(line.Name, input.WorkflowId, line.FromNodeId, line.ToNodeId, line.Conditions)).ToList()
                , input.WorkflowNodes.Select(node => new WorkflowNode(node.Id, input.WorkflowId, node.Name, node.NodeType, node.DrawingInfo, node.IsWaitingAllUser, node.UserSelectors, node.RejectNodes, node.ProveMode, node.IsAutoHandleSameUserStep, node.IsIgnoreCreator)).ToList());
        }

        /// <summary>
        /// 获取所有流程列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflows")]
        public async Task<PageResult<WorkflowDto>> GetAllWorkflows([FromQuery] GetAllWorkflowInput input)
        {

            var items = await workflowRepository.GetPagedListAsync(w => !w.Deleted && (input.Name.IsNullOrWhiteSpace() || w.Name.Contains(input.Name)), input.SkipCount, input.MaxResultCount, "IsLock desc, ModifiedTime desc");
            var count = await workflowRepository.GetCountAsync(w => !w.Deleted && (input.Name.IsNullOrWhiteSpace() || w.Name.Contains(input.Name)));
            var workflowIds = items.Select(i => i.Id).ToArray();
            var versionCount = await workflowRepository.GetWorkflowVersionCount(workflowIds);

            var wf4formDesign = items.Select(i => new WorkflowId4FormDesign(i.Id, i.ActiveVersion)).ToArray();
            var activeFromVersion = await formDesignManager.GetFormDesignsOfWorkflowId(wf4formDesign);
            var result = new PageResult<WorkflowDto>
            {
                Items = items.Select(i =>
            {
                var itemOut = i.Adapt<WorkflowDto>();
                itemOut.VersionCount = versionCount.GetOrDefault(itemOut.Id);
                itemOut.ActiveFormVersion = activeFromVersion.FirstOrDefault(af => af.WorkflowId.Id == itemOut.Id && af.WorkflowId.Version == itemOut.ActiveVersion)?.ActiveVersion ?? 0;
                return itemOut;
            }).ToList(),
                Total = count
            };
            return result;
        }

        /// <summary>
        /// 获取所有流程列表（带版本信息）
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAllWorkflowsWithVersion")]
        public async Task<List<GetAllWorkflowsWithVersionOutput>> GetAllWorkflowsWithVersion()
        {
            var workflows = await workflowManager.GetAllWorkflowsWithVersion();
            return workflows.Adapt<List<GetAllWorkflowsWithVersionOutput>>();
        }

        /// <summary>
        /// 创建新流程设计或者更新流程设计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("CreateOrUpdateWorkFlow")]
        public async Task<Workflow> CreateOrUpdateWorkFlow(UpdateWorkFlowInput input)
        {
            return await workflowManager.CreateUpdateWorkflow(input.WorkflowId.Id, input.Name, input.Des, input.Type, input.WorkflowId.VersionNo, input.DrawingInfo, input.VersionDescription
                , input.WorkflowLines.Select(line => new WorkflowLine(line.Name, input.WorkflowId, line.FromNodeId, line.ToNodeId, line.Conditions)).ToList()
                , input.WorkflowNodes.Select(node => new WorkflowNode(node.Id, input.WorkflowId, node.Name, node.NodeType, node.DrawingInfo, node.IsWaitingAllUser, node.UserSelectors, node.RejectNodes, node.ProveMode, node.IsAutoHandleSameUserStep, node.IsIgnoreCreator)).ToList());
        }

        /// <summary>
        /// 锁定流程设计版本（锁定后不允许编辑）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("LockWorkflowVersion")]
        public async Task<bool> LockWorkflowVersion(LockWorkflowVersionInput input)
        {
            if (input == null)
            {
                return false;
            }
            return await workflowManager.LockWorkflowVersion(input.id, input.versionNo);
        }

        /// <summary>
        /// 锁定流程设计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("LockWorkflow")]
        public async Task<bool> LockWorkflow(LockWorkflowInput input)
        {
            if (input == null)
            {
                return false;
            }
            return await workflowManager.LockWorkflow(input.id);
        }
    }
}
